
#pragma once

#include <vector>
#include <ttg/threads.h>

//Definition of used class.
class PrimeFinder;

//Pool with prime number finders.
//This class is thread-safe.
class PrimeFinderPool
{
	private:
		std::vector<bool *> buffers;
		size_t buffer_size;
		ttg::threads::FastCriticalSection locker;
	private:
		//Returns finder.
		//Note: it should be released by "releaseFinder()" method.
		PrimeFinder *acquireFinder();
		//Releases finder.
		void releaseFinder(PrimeFinder *&finder);
	public:
		//Creates pool, that uses buffers with required sizes.
		PrimeFinderPool(size_t buffer_size = 1024 * 1024)
		{ this->buffer_size = buffer_size; }
		//Finds count of primes number, that is located in required range.
		ttg::math::uint64 findPrimes(ttg::math::uint64 lo, ttg::math::uint64 hi);
		~PrimeFinderPool();
};

//Finds all prime numbers from the required range.
//Can be created only via PrimeFinderPool.
class PrimeFinder
{
	private:
		bool *buffer;
		size_t buffer_size;
		//Creates finder with required buffer.
		PrimeFinder(bool *buffer, size_t buffer_size)
		{
			this->buffer = buffer;
			this->buffer_size = buffer_size;
			clearBuffer(0);
		}
		//Clears whole buffer and returns count of values with "true" flags,
		//that is located in range.
		size_t clearBuffer(size_t range_length);
		//Strikes required range (that is located in buffer) by number.
		void strikeNumber(size_t number,
						  ttg::math::uint64 range_start, size_t range_length);
		//Finds count of primes number, that is located in required range.
		//Note: length of the range should be <= than buffer_size;
		size_t findPrimesUsingBuffer(ttg::math::uint64 range_start, size_t range_length);
	public:
		//Finds count of primes number, that is located in required range.
		ttg::math::uint64 findPrimes(ttg::math::uint64 lo, ttg::math::uint64 hi);
	friend class PrimeFinderPool;
};